using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace XGameFrame
{
    /// <summary>
    /// moebis:
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class InputHandler : Microsoft.Xna.Framework.GameComponent
    {

        #region Keyboard Field Region

        static KeyboardState keyboardState;
        static KeyboardState lastKeyboardState;

        #endregion

        #region Mouse Field Region
        static MouseState lastMouseState;
        static MouseState currentMouseState;

        #endregion

        #region Game Pad Field Region

        static GamePadState[] gamePadStates;
        static GamePadState[] lastGamePadStates;

        #endregion

        #region Keyboard Property Region

        /// <summary>
        /// Get current KeyboardState
        /// </summary>
        public static KeyboardState KeyboardState
        {
            get { return keyboardState; }

        }
        /// <summary>
        /// Get last KeyboardState
        /// </summary>
        public static KeyboardState LastKeyboardState
        {
            get { return lastKeyboardState; }

        }

        #endregion

        #region Mouse Property region
        /// <summary>
        /// Get last MouseState or set it
        /// </summary>
        public static MouseState LastMouseState
        {
            get { return lastMouseState; }
            set { lastMouseState = value; }
        }

        /// <summary>
        /// Get current MouseState or set it
        /// </summary>
        public static MouseState CurrentMouseState
        {
            get { return currentMouseState; }
            set { currentMouseState = value; }
        }

        public static Vector2 CurrentMousePosition
        {
            get { return new Vector2(currentMouseState.X, currentMouseState.Y); }
        }
        #endregion

        #region Game Pad Property Region

        /// <summary>
        /// Get current GamePadState
        /// </summary>
        public static GamePadState[] GamePadStates
        {
            get { return gamePadStates; }
        }

        /// <summary>
        /// Get lase GamePadState
        /// </summary>
        public static GamePadState[] LastGamePadStates
        {
            get { return lastGamePadStates; }
        }

        #endregion



        #region Constructor Region

        /// <summary>
        /// Constructor for a new InputHandler
        /// </summary>
        /// <param name="pGame">Game parameter</param>
        public InputHandler(Game pGame)
            : base(pGame)
        {
            keyboardState = Keyboard.GetState();
            CurrentMouseState = Mouse.GetState();
            gamePadStates = new GamePadState[Enum.GetValues(typeof(PlayerIndex)).Length];

            foreach (PlayerIndex _index in Enum.GetValues(typeof(PlayerIndex)))
                gamePadStates[(int)_index] = GamePad.GetState(_index);
        }
        #endregion




        #region XNA Methods
        
        /// <summary>
        /// Initialize the InputHandler from GameComponent
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
        }

        /// <summary>
        /// Do Logic for InputHandler
        /// </summary>
        /// <param name="pGameTime">Games pGameTime controlling hanging</param>
        public override void Update(GameTime pGameTime)
        {
            lastKeyboardState = keyboardState;
            keyboardState = Keyboard.GetState();
            LastMouseState = CurrentMouseState;
            CurrentMouseState = Mouse.GetState();

            lastGamePadStates = (GamePadState[])gamePadStates.Clone();
            foreach (PlayerIndex index in Enum.GetValues(typeof(PlayerIndex)))
                gamePadStates[(int)index] = GamePad.GetState(index);

            base.Update(pGameTime);
        }
        #endregion

        #region General Method Region

        /// <summary>
        /// Obsolete ?!
        /// </summary>
        public static void Flush()
        {
            lastKeyboardState = keyboardState;
        }

        #endregion


        #region Keyboard Region
        /// <summary>
        /// Detect if Key is released
        /// </summary>
        /// <param name="pkey">The keys on the keyboard</param>
        /// <returns>true if Key is released, else false</returns>
        public static bool KeyReleased(Keys pKey)
        {
            return keyboardState.IsKeyUp(pKey) &&
                lastKeyboardState.IsKeyDown(pKey);
        }
        /// <summary>
        /// Detect if Key is pressed
        /// </summary>
        /// <param name="pkey">The keys on the keyboard</param>
        /// <returns>true if Key is pressed, else false</returns>
        public static bool KeyPressed(Keys pKey)
        {
            return keyboardState.IsKeyDown(pKey) &&
                lastKeyboardState.IsKeyUp(pKey);
        }
        
        /// <summary>
        /// Detect if Key is hold down
        /// </summary>
        /// <param name="pkey">The keys on the keyboard</param>
        /// <returns>true if Key is hold down, else false</returns>
        public static bool KeyDown(Keys pKey)
        {
            return keyboardState.IsKeyDown(pKey);
        }

        #endregion

        #region Mouse Region
        
        /// <summary>
        /// Detect if the Mouse has a new State
        /// </summary>
        /// <returns>true if MouseState changed, else false</returns>
        public static bool MouseMove()
        {
            if(LastMouseState != CurrentMouseState)
                return true;
            return false;
        }
        /// <summary>
        /// Detect if the LeftMouseButton is pressed
        /// </summary>
        /// <returns>true if LeftMouseButton is pressed, else false</returns>
        public static bool MouseButtonLeftPressed()
        {
            return (CurrentMouseState.LeftButton == ButtonState.Released &&
                    LastMouseState.LeftButton == ButtonState.Pressed);
        }
        /// <summary>
        /// Detect if the RightMouseButton is pressed
        /// </summary>
        /// <returns>true if RightMouseButton is pressed, else false</returns>
        public static bool MouseButtonRightPressed()
        {
            return (CurrentMouseState.RightButton == ButtonState.Released &&
                    LastMouseState.RightButton == ButtonState.Pressed);
        }

        /// <summary>
        /// Detect if the left button are hold
        /// </summary>
        /// <returns>true if LeftMouseButton is hold, else false</returns>
        public static bool MouseButtonLeftHold()
        {
            return (CurrentMouseState.LeftButton == ButtonState.Pressed &&
                    LastMouseState.LeftButton == ButtonState.Pressed);
        }
        
        /// <summary>
        /// Detect if the right button are hold
        /// </summary>
        /// <returns>true if RightMouseButton is hold, else false</returns>
        public static bool MouseButtonRightHold()
        {
            return (CurrentMouseState.RightButton == ButtonState.Pressed &&
                    LastMouseState.RightButton == ButtonState.Pressed);
        }
        /// <summary>
        /// Detect if the scrollwheel has moved
        /// </summary>
        /// <returns>true if the scrollwheel has moved,else false</returns>
        public static bool MouseScrollWheelMove()
        {
            return (CurrentMouseState.ScrollWheelValue != LastMouseState.ScrollWheelValue);
        }
        /// <summary>
        /// Returns the Position from the mouse
        /// </summary>
        /// <returns>position from mouse</returns>
        public static Vector2 MousePosition()
        {
            return new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
        }


        #endregion

        #region Game Pad Region

        /// <summary>
        /// Detect if the GamePadButton is released
        /// </summary>
        /// <returns>true if GamePadButton is released, else false</returns>
        public static bool ButtonReleased(Buttons pButton, PlayerIndex pIndex)
        {
            return gamePadStates[(int)pIndex].IsButtonUp(pButton) &&
            lastGamePadStates[(int)pIndex].IsButtonDown(pButton);
        }

        /// <summary>
        /// Detect if the GamePadButton was pressed
        /// </summary>
        /// <returns>true if GamePadButton was was, else false</returns>
        public static bool ButtonPressed(Buttons pButton, PlayerIndex pIndex)
        {
            return gamePadStates[(int)pIndex].IsButtonDown(pButton) &&
            lastGamePadStates[(int)pIndex].IsButtonUp(pButton);
        }

        /// <summary>
        /// Detect if the GamePadButton is hold down
        /// </summary>
        /// <returns>true if GamePadButton is hold down, else false</returns>
        public static bool ButtonDown(Buttons pButton, PlayerIndex pIndex)
        {
            return gamePadStates[(int)pIndex].IsButtonDown(pButton);
        }

        #endregion

    }
}
